home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
L' Effet Pommier 3
/
L'Effet Pommier - Volume 03.iso
/
Programmation
/
gray image 2.1
/
filter.h
< prev
next >
Wrap
Text File
|
1995-05-31
|
7KB
|
231 lines
// This may look like C code, but it is really -*- C++ -*-
/*
************************************************************************
*
* Grayscale Image Filtration
*
* Declaration of functions/procedures (generally grouped together
* under the FilterIt class umbrella) that do linear and some non-linear
* image filtration and related transfromations. Most of the operations
* do filtration "inplace"
*
* Note that class FilterIt is a friend of IMAGE, so it's privy of
* IMAGE internals and can use them to make processing faster.
*
* $Id: filter.h,v 2.0 1995/03/18 18:15:48 oleg Exp oleg $
*
************************************************************************
*/
#ifndef __GNUC__
#pragma once
#endif
#ifndef _filter_h
#define _filter_h
#ifdef __GNUC__
#pragma interface
#endif
#include "image.h"
#include "std.h"
/*
*------------------------------------------------------------------------
* Convolution kernels
*
* Kernel coeffs are stored as rational numbers with some common denominator,
* which can be either 1 (that is, all coeffs are ints) or power of two, or
* some arbitrary card number. We use a family of CommonDenom classes for each
* of those situations. Each members of the family defines how to
* execute a division of long int by a denominator most efficiently.
* The classes are then used in "templates" in actual filtration algorithm
*/
class CommonDenomOne
{
public:
inline int divide(long int x) const { return x; }
};
class over_2_up
{
card exponent;
public:
over_2_up(const card _exp) : exponent(_exp) {}
inline int divide(long int x) const { return x>>exponent; }
};
class CommonDenom
{
card denom;
public:
CommonDenom(const card _denom) : denom(_denom) {}
inline int divide(long int x) const { return x/(signed)denom; }
};
// 1D 3-point convolution kernel
template <class Denom>
class ConvKernel3
{
const int am1,a0,ap1; // a[k-1], a[k], a[k+1] coeffs
const Denom common_denominator;
public:
ConvKernel3(const int _am1, const int _a0, const int _ap1,
const Denom denom) :
am1(_am1), a0(_a0), ap1(_ap1), common_denominator(denom) {}
inline int convolve(const GRAY_SIGNED pm1, const GRAY_SIGNED p0,
const GRAY_SIGNED pp1) const
{ return common_denominator.divide(pm1*am1 + p0*a0 + pp1*ap1); }
};
// Expand templates right here...
//template class ConvKernel3<CommonDenomOne>;
// Convolution kernels
// all coeffs integers
inline ConvKernel3<CommonDenomOne> conv_kernel(
const int am1, const int a0, const int ap1)
{ return ConvKernel3<CommonDenomOne>(am1,a0,ap1,CommonDenomOne()); }
inline ConvKernel3<over_2_up>
conv_kernel(const int am1, const int a0, const int ap1, over_2_up denom)
{ return ConvKernel3<over_2_up>(am1,a0,ap1,denom); }
inline ConvKernel3<CommonDenom>
conv_kernel(const int am1, const int a0, const int ap1, CommonDenom denom)
{ return ConvKernel3<CommonDenom>(am1,a0,ap1,denom); }
/*
*------------------------------------------------------------------------
* Look-up tables
* to specify a mapping operation GRAY -> GRAY
*/
class LookupT
{
friend class FilterIt;
GRAY min_val, max_val; // in the GRAY domain of the mapping
GRAY * table; // mapping itself
card no_entries; // in the table
// init the LookupT but don't fill in
// the table
void allocate(const GRAY _min_val, const GRAY _max_val);
enum { Preallocated_no = 256 }; // Allocate ahead that many entries
GRAY preallocated [Preallocated_no];
public:
// What to do with pixels that outside
// [min_val,max_val] when doing mapping
enum FringeHandling { CoerceFringes, LeaveFringes };
// Just to make constructing some common
// look-up tables sweeter...
struct Identical { const card depth; Identical(const card _d) : depth(_d){}};
struct MapTo {
const GRAY from, to;
MapTo(const GRAY _from, const GRAY _to) : from(_from), to(_to) {}
};
struct DownGRAY {
const card depth_from, depth_to;
DownGRAY(const card _f, const card _t) : depth_from(_f), depth_to(_t) {}
};
// Identical pixel mapping for an image of
// specified depth
LookupT(const Identical id);
// Build a table (with one entry) to map
// just one particular pixel
LookupT(const MapTo map_one);
// Build a table to reduce image depth from
// one value to another (that is, build a
// stripy table)
LookupT(const DownGRAY downgray);
LookupT(const LookupT& another); // standard assignment stuff
LookupT& operator= (const LookupT& another);
~LookupT(void);
// Getting hold of and/or modifying
// specific mappings
GRAY& operator[] (const GRAY val);
GRAY operator[] (const GRAY val) const;
// Convolve two Lookup tables, that is,
// translate pixels of this according to
// another table
// (Lookup table composition)
LookupT& apply(const LookupT& another,
const FringeHandling fringe_handling);
GRAY q_min(void) const { return min_val; }
GRAY q_max(void) const { return max_val; }
};
inline GRAY& LookupT::operator[] (const GRAY val)
{
if( val < min_val || val > max_val )
_error("The pixel value %d to look up is out of range [%d,%d]",
val,min_val,max_val);
return table[val-min_val];
}
inline GRAY LookupT::operator[] (const GRAY val) const
{ return (*(LookupT *)this)[val]; }
/*
*------------------------------------------------------------------------
* The umbrella class FilterIt itself
*
*/
class FilterIt
{
IMAGE& image; // Image under filtration
void operator=(const FilterIt&); // is not implemented, ergo, is
// not allowed
IMAGE& median_3_row(void); // 3-point row-wise filtration
IMAGE& median_3_col(void); // 3-point col-wise filtration
IMAGE& median_5_row(void); // 5-point row-wise filtration
IMAGE& median_5_col(void); // 5-point col-wise filtration
public:
// How to apply filters
enum Direction { Columns, Rows, RowsAndColumns };
FilterIt(IMAGE& _image) : image(_image) {}
IMAGE& median(const Direction how, const int win_size = 3);
// Convolution methods
// Templates don't work inside the class 8:(
// ("method templates" would do, by they
// aren't supported yet)
#define CONV_DECL(Kernel,Denom) \
IMAGE& conv_row(const Kernel<Denom>& kernel); \
IMAGE& conv_col(const Kernel<Denom>& kernel); \
IMAGE& conv(const Kernel<Denom>& kernel, \
const Direction how = RowsAndColumns); \
CONV_DECL(ConvKernel3,CommonDenomOne)
CONV_DECL(ConvKernel3,over_2_up)
CONV_DECL(ConvKernel3,CommonDenom)
#undef CONV_DECL
// Translate image pixels according to
// the look-up table
IMAGE& translate(const LookupT& lookupt,
const LookupT::FringeHandling fringe_handling);
};
#endif